"""Some parts taken or based on www.devshed.com/c/a/Python/PyGame-for-Game-Development-Font-and-Sprites/3/"""
"""Some parts take or based on http://www.linuxjournal.com/article/7694"""

import math, re
from Graphics import * #@UnusedWildImport
from Objects import Missile

class Ship(pygame.sprite.Sprite):
    def __init__(self, screenDim, spawnLoc=[0, 0], ship_image = "ship2_1.png"):
        screen = Screen()
        pygame.sprite.Sprite.__init__(self)
        
        """Save a copy of the screen's rectangle"""
        self.screen = pygame.display.get_surface()
        
        """Create a variable to store the previous position of the sprite"""
        self.old = (0, 0, 0, 0)
        
        self.image, self.rect = screen.load_image(ship_image)
        self.original_image = self.image
        
        #NOTE: I had to make to two different positions for the ship,
        #one to render it to the center of the screen, and
        #one to render the correct relative background for the map.
        
        #Adjust the ship's position based off of
        #the screen's dimensions - the ship's dimensions (centered)
        shipDem = self.getDimensions()
        self.rect.x = screenDim[0] / 2 - shipDem[0] / 2
        self.rect.y = screenDim[1] / 2 - shipDem[1] / 2
        
        #Ship's position, determined by its spawn location
        #Measured at the center of the image!
        self.spawnLoc = spawnLoc
        self.screenDim = screenDim
        self.position = self.spawnLoc
        self.max_speed = 6
        
        #Grid information
        self.grid = (int(self.position[0] / 500), int(self.position[1] / 500))
        
        """Set initial speed, angle, etc"""
        self.angle = 0
        self.speed = 0
        
        #Pattern for regular expression used in displaying self.position
        self.pattern = re.compile('(\d+)(\.)*(\d+)*\, (\d+)(\.)*(\d+)*')
        
        self.powerUps = []
        self.gun_mode = "regular"
        self.has_speed_boost = False
        
    
    def rotate(self, degrees):
        self.angle = (self.angle + degrees) % 360
        self.image = pygame.transform.rotate(self.original_image, self.angle)
        self.rect = self.image.get_rect(center=self.rect.center)
        
    def accelerate(self):
        self.speed += 0.5
        if(self.speed > self.max_speed):
            self.speed = self.max_speed
        
    def decelerate(self):
        self.speed -= 1
        if(self.speed < -self.max_speed):
            self.speed = -self.max_speed
            
    def fire(self, screen, pmissile_sprite):
        if(self.has_speed_boost == True):
            if(self.gun_mode == "regular"):
                pmissile_sprite.add(Missile(screen, self.position, self.angle, True))
            elif(self.gun_mode == "powerUpWeapon"):
                pmissile_sprite.add(Missile(screen, self.position, self.angle, True))
                pmissile_sprite.add(Missile(screen, self.position, self.angle - 30, True))
                pmissile_sprite.add(Missile(screen, self.position, self.angle + 30, True))
        else:
            if(self.gun_mode == "regular"):
                pmissile_sprite.add(Missile(screen, self.position, self.angle))
            elif(self.gun_mode == "powerUpWeapon"):
                pmissile_sprite.add(Missile(screen, self.position, self.angle))
                pmissile_sprite.add(Missile(screen, self.position, self.angle - 30))
                pmissile_sprite.add(Missile(screen, self.position, self.angle + 30))
        
    def grantPowerUp(self, powerUp, ticks, playership_sprite = None):
        self.powerUps.append(powerUp)
        if(powerUp.name) == "speed":
            self.__applySpeedPowerUp()
        
        if(powerUp.name) == "weapon":
            self.__applyWeaponPowerUp()
            
        if(powerUp.name) == "shield":
            self.__applyShieldPowerUp(playership_sprite)
            
    def checkPowerUps(self, current_ticks):
        for powerUp in self.powerUps:
            if powerUp.is_consumed(current_ticks):
                if powerUp.name == "speed":
                    self.__unapplySpeedPowerUp()
                    self.powerUps.remove(powerUp)
                
                if powerUp.name == "weapon":
                    self.__unapplyWeaponPowerUp()
                    self.powerUps.remove(powerUp)
        
                if powerUp.name == "shield":
                    self.__unapplyShieldPowerUp()
        
    def __applySpeedPowerUp(self):
        self.max_speed += 10
        self.has_speed_boost = True
    
    def __applyWeaponPowerUp(self):
        self.gun_mode = "powerUpWeapon"
        
    def __applyShieldPowerUp(self, playership_sprite):
        pass
    
    def __unapplySpeedPowerUp(self):
        self.max_speed -= 10
        self.speed = 5
        self.has_speed_boost = False
        
    def __unapplyWeaponPowerUp(self):
        self.gun_mode = "regular"
        
    def __unapplyShieldPowerUp(self):
        pass
        
    #This function simply updates the ship's position/grid and
    #Ensures that the ship hasn't passed the map's borders
    def update(self, mapSize):
        
        scale_x = math.cos(math.radians(self.angle))
        scale_y = math.sin(math.radians(self.angle))
        
        velocity_x = (self.speed * scale_y)
        velocity_y = (self.speed * scale_x)
        
        self.position = [self.position[0] - velocity_x, self.position[1] - velocity_y]
        
        """Check to see if we are at the edge of the map"""
        #Left limit
        if self.position[0] < 0:
            self.position[0] = 0
        #Right limit
        elif self.position[0] > (mapSize[0] - self.rect.width):
            self.position[0] = mapSize[0] - self.rect.width
        #Top limit
        if self.position[1] < 0:
            self.position[1] = 0
        #Bottom limit
        elif self.position[1] > (mapSize[1] - self.rect.height):
            self.position[1] = mapSize[1] - self.rect.height
        
        #Update grid information
        self.grid = (int(self.position[0] / 500), int(self.position[1] / 500))
            
    #Return (Width, Height) of the player's ship
    def getDimensions(self):
        return (self.rect.width, self.rect.height)
    
    #Change ship's spawn point
    def changeSpawn(self, spawnLoc):
        self.spawnLoc = spawnLoc
        return True
    
    def respawn(self):
        #Reset values
        self.position = self.spawnLoc
        self.speed = 0
        self.angle = 0
        #Changes in angle will not appear unless rotate is called afterward
        self.rotate(0)
        
    
    #Display data onscreen (useful for debugging, etc.)
    def displayData(self, baseCollide):
        if pygame.font:
            font = pygame.font.Font(None, 20)
            #Position
            position = str(self.position)
            position = (int(self.pattern.search(position).group(1)), int(self.pattern.search(position).group(4)))
            
            text = font.render(str(position), 1, (255, 255, 255))
            textpos = text.get_rect(right=self.screen.get_width())
            self.screen.blit(text, textpos)
            #Grid
            text = font.render(str(self.grid), 1, (255, 255, 255))
            textpos = text.get_rect(right=self.screen.get_width(), top=font.get_linesize())
            self.screen.blit(text, textpos)
            #Collide
            if baseCollide == True:
                text = font.render("Spawn point set", 1, (255, 255, 255))
                textpos = text.get_rect(right=self.screen.get_width(), top=font.get_linesize()*2)
                self.screen.blit(text, textpos)
            return True
        else:
            return False
